package org.etherframework.core
{
	import flash.events.Event;
	import flash.utils.Proxy;
	
	import mx.utils.UIDUtil;
	
	import org.etherframework.behaviour.rules.events.FeedbackEvent;
	import org.etherframework.core.events.DataEvent;
	import org.etherframework.core.events.InteractionEvent;
	import org.etherframework.dependency.DependencyInfo;
	import org.etherframework.wire.wirings.proxyClasses.ProxyInfo;

	public class BridgeInteraction implements IBridgeInteraction
	{
		private var bridge:IBridge;
		
		public function BridgeInteraction(bridge:IBridge)
		{
			this.bridge = bridge;
		}
		
		public function getDependency(item:String, access:String, domain:String):Object
		{
			AccessDomainValidator.validate(access, domain);
			
			var beanInfo:Object = bridge.getBean(item);
			
			if (!beanInfo && (access != Access.LOCAL))
			{
				var evt:InteractionEvent = new InteractionEvent(InteractionEvent.GET_DEPENDENCY + item);
				evt.data = item;
				bridge.dispatch(evt, access, domain);
				beanInfo = evt.result;
			}
			
			return beanInfo;
		}
		
		public function getProxy(item:String, access:String, domain:String, data:* = null):Array
		{
			AccessDomainValidator.validate(access, domain);
			
			var items:Array = [];
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.GET_PROXY + item);
			evt.data = data;
			evt.result = items;
			bridge.dispatch(evt, access, domain);
			
			return items;
		}
		
		public function getMediation(item:String, data:Array, access:String, domain:String):*
		{
			AccessDomainValidator.validate(access, domain);
			
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.MEDIATION + item);
			evt.data = data;
			evt.result = [];
			bridge.dispatch(evt, access, domain);
			
			return evt.result;
		}
		
		public function listenGetDependency(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.GET_DEPENDENCY + item, handler, access, domain);
		}
		
		public function unlistenGetDependency(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.GET_DEPENDENCY + item, handler, access, domain);
		}
		
		public function listenDependencyAdded(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.DEPENDENCY_ADDED + item, handler, access, domain);
		}
		
		public function unlistenDependencyAdded(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.DEPENDENCY_ADDED + item, handler, access, domain);
		}
		
		public function listenDependencyRemoved(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.DEPENDENCY_REMOVED + item, handler, access, domain);
		}
		
		public function unlistenDependencyRemoved(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.DEPENDENCY_REMOVED + item, handler, access, domain);
		}
		
		public function dispatchDependencyAdded(info:DependencyInfo, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.DEPENDENCY_ADDED + info.name);
			evt.data = info;
			bridge.dispatch(evt, access, domain);
			
			if (info.type)
			{
				evt = new InteractionEvent(InteractionEvent.DEPENDENCY_ADDED + info.type);
				evt.data = info;
				bridge.dispatch(evt, access, domain);
			}
			
			evt = new InteractionEvent(InteractionEvent.DEPENDENCY_ADDED);
			evt.data = info;
			bridge.dispatch(evt, access, domain);
		}
		
		public function dispatchDependencyRemoved(info:DependencyInfo, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.DEPENDENCY_REMOVED + info.name);
			evt.data = info;
			bridge.dispatch(evt, access, domain);
			
			if (info.type)
			{
				evt = new InteractionEvent(InteractionEvent.DEPENDENCY_REMOVED + info.type);
				evt.data = info;
				bridge.dispatch(evt, access, domain);
			}
			
			evt = new InteractionEvent(InteractionEvent.DEPENDENCY_REMOVED);
			evt.data = info;
			bridge.dispatch(evt, access, domain);
		}
		
		public function listenGetProxy(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.GET_PROXY + item, handler, access, domain);
		}
		
		public function unlistenGetProxy(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.GET_PROXY + item, handler, access, domain);
		}
		
		public function listenProxyAdded(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.PROXY_ADDED + item, handler, access, domain);
		}
		
		public function unlistenProxyAdded(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.PROXY_ADDED + item, handler, access, domain);
		}
		
		public function dispatchProxyAdded(proxyInfo:ProxyInfo, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.PROXY_ADDED + proxyInfo.name);
			evt.data = proxyInfo;
			bridge.dispatch(evt, access, domain);
		}
		
		public function dispatchProxyRemoved(proxyInfo:ProxyInfo, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.PROXY_REMOVED + proxyInfo.name);
			evt.data = proxyInfo;
			bridge.dispatch(evt, access, domain);
		}
		
		public function listenProxyRemoved(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.PROXY_REMOVED + item, handler, access, domain);
		}
		
		public function unlistenProxyRemoved(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.PROXY_REMOVED + item, handler, access, domain);
		}
		
		public function listenMediation(item:String, handler:Function, access:String, domain:String, priority:Number = 0):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.MEDIATION + item, handler, access, domain, false, priority);
		}
		
		public function unlistenMediation(item:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.MEDIATION + item, handler, access, domain, false);
		}
		
		public function listenEvent(type:String, handler:Function, access:String, domain:String, useCapture:Boolean = false, 
									priority:Number = 0, useWeakReference:Boolean = false):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.EVENT + type, handler, 
				access, domain, useCapture, priority, useWeakReference);
		}
		
		public function unlistenEvent(type:String, handler:Function, access:String, domain:String, useCapture:Boolean = false):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.EVENT + type, handler, 
				access, domain, useCapture);
		}
		
		public function dispatchEvent(event:Event, initiator:Object, access:String, domain:String):Boolean
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.EVENT + event.type);
			evt.initiator = initiator;
			evt.data = event;
			
			return bridge.dispatch(evt, access, domain);
		}
		
		public function listenFeedback(type:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.FEEDBACK + type, handler, access, domain);
		}
		
		public function unlistenFeedback(type:String, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.FEEDBACK + type, handler, access, domain);
		}
		
		public function dispatchFeedback(item:String, feedback:FeedbackEvent, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:DataEvent = new DataEvent(InteractionEvent.FEEDBACK + item);
			evt.data = feedback;
			bridge.dispatch(evt, access, domain);
		}
		
		public function listenControllerAdded(bridgeToken:String, handler:Function):void
		{
			bridge.listen(InteractionEvent.CONTROLLER_ADDED + bridgeToken, handler);
		}
		
		public function unlistenControllerAdded(bridgeToken:String, handler:Function):void
		{
			bridge.unlisten(InteractionEvent.CONTROLLER_ADDED + bridgeToken, handler);
		}
		
		public function listenControllerRemoved(bridgeToken:String, handler:Function):void
		{
			bridge.listen(InteractionEvent.CONTROLLER_REMOVED + bridgeToken, handler);
		}
		
		public function unlistenControllerRemoved(bridgeToken:String, handler:Function):void
		{
			bridge.unlisten(InteractionEvent.CONTROLLER_REMOVED + bridgeToken, handler);
		}
		
		public function dispatchItemWired(item:Object, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.ITEM_WIRED + UIDUtil.getUID(item));
			bridge.dispatch(evt, access, domain);
		}
		
		public function listenItemWired(item:Object, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.ITEM_WIRED + UIDUtil.getUID(item), handler, access, domain);
		}
		
		public function unlistenItemWired(item:Object, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.ITEM_WIRED + UIDUtil.getUID(item), handler, access, domain);
		}
		
		public function dispatchItemUnwired(item:Object, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			var evt:InteractionEvent = new InteractionEvent(InteractionEvent.ITEM_UNWIRED + UIDUtil.getUID(item));
			bridge.dispatch(evt, access, domain);
		}
		
		public function listenItemUnwired(item:Object, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.listen(InteractionEvent.ITEM_UNWIRED + UIDUtil.getUID(item), handler, access, domain);
		}
		
		public function unlistenItemUnwired(item:Object, handler:Function, access:String, domain:String):void
		{
			AccessDomainValidator.validate(access, domain);
			bridge.unlisten(InteractionEvent.ITEM_UNWIRED + UIDUtil.getUID(item), handler, access, domain);
		}
	}
}